<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
	<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
	<meta http-equiv="pragma" content="no-cache" />
    <meta name="author" content="Jayli" />
	<meta name="keywords" content="淘宝UED 前端工程师 拔赤" />	
	<meta name="description" content="淘宝前端工程师拔赤，关注尖端前端技术，关注yui" />
	<meta http-equiv="imagetoolbar" content="no" />
	<meta name="title" content="拔赤的文章列表" />
    <title>基于YUI3的方法链式调用</title>
    <link href="http://jayli.github.com/blog/atom.xml" rel="alternate" title="setImpl" type="application/atom+xml" />
    <link rel="stylesheet" href="http://jayli.github.com/blog/media/css/style.css">
    <link rel="stylesheet" href="http://jayli.github.com/blog/media/css/github.css">
	<style>
	</style>
    <script type="text/javascript" src="http://jayli.github.com/blog/media/js/highlight.pack.js"></script>
    <script type="text/javascript">
      hljs.initHighlightingOnLoad();
    </script>
	<!--[if lte IE 8]>
	<script src="http://a.tbcdn.cn/apps/lottery/00023/index-v3/js/html5.js"></script>
	<![endif]-->
	<meta name="baidu-tc-verification" content="afb6c9df553ef3493d9ee65263df0d55" />
	<script src="http://siteapp.baidu.com/static/webappservice/uaredirect.js" type="text/javascript"></script><script type="text/javascript">uaredirect("http://m.zoojs.org", "http://jayli.github.com/blog");</script>
  </head>
  <body>
    <div id="container">
      <div id="main" role="main">
        <header>
        <h1>基于YUI3的方法链式调用</h1>
        </header>
        <nav>
        <span><a title="home page" class="" href="/blog/index.html">home</a></span>
        <span><a title="tags" class="" href="/blog/tags.html">tags</a></span>
        <span><a title="about" class="" href="/blog/about.html">about me</a></span>
        <span><a title="flickr" class="" href="http://www.flickr.com/photos/lijing00333">flickr</a></span>
        <span><a title="blogroll" class="" href="/blog/links.html">links</a></span>
        <span><a title="projects" class="" href="/blog/projects.html">projects</a></span>
        <span><a title="subscribe me" class="" href="/blog/atom.xml">feed</a></span>
        </nav>
        <article class="content">
        <section class="post">
<p>yui3.0.0beta终于千呼万唤使出来，鼓掌！！！下载在这里：http://developer.yahoo.com/yui/3/</p>

<p>说到js的方法链式调用，的确，jquery确实给了wd们很多美好的回忆；所谓链式调用是一种语法上的小hack，也仅仅停留在代码级别，不过这种方法确实能使工程师用少量的代码达到复杂的操作目的，是一种很值得推广的技巧。不过yui2在这方面没作多少工作，yui3开始大量的使用这种技巧，让人猛然感觉语法风格和yui2的迥异。</p>

<p>在yui2中，我要对某个dom元素执行一系列的操作必须要这样：</p>

<pre><code>var el = YAHOO.util.Dom.get(‘id’);
YAHOO.util.Dom.addClass(el,’className’);
YAHOO.util.Dom.setStyle(el,’display’,'block’);
</code></pre>

<p>在yui3中可以这样：</p>

<pre><code>Y.get(‘#id’).addClass(‘className’).setStyle(‘display’,'block’);
</code></pre>

<p>语法上简洁了很多，这种写法就是所谓的链式调用。yui3的链式调用如何实现的、扩展行好不好呢？上篇介绍yui3的装饰者的时候涉及到一点这方面的内容：方法的声明＋定义。比如，要对dom节点扩展一个fuck行为，则需要：</p>

<pre><code>Y.mix(Y.DOM,{
    fuck:function(o){
        alert(o.innerHTML);//定义
    }
});
Y.Node.addDOMMethods([
    'fuck'//声明
]);
</code></pre>

<p>为什么不直接定义，而要加一个“声明“出来，这种做法是为了降低库模块之间的耦合，即我在定义这个fuck的时候不必知晓DOM内部的逻辑，DOM 在调用fuck的时候则会自动返回一个包装好的Node，这种做法增加了库的可扩展性。再来看一个例子，我要模拟一个‘人’的行为，分别用yui3和不用库来作，看两者的区别，基于yui3：</p>

<pre><code>YUI().use(‘node’, function(Y){
    Y.mix(Y.DOM,{
        eat:function(o){
            o.innerHTML += ‘吃！’;
        },
        drink:function(o){
            o.innerHTML += ‘喝！’;
        },
        shit:function(o){
            o.innerHTML += ‘拉！’;
        },
        pee:function(o){
            o.innerHTML += ‘撒！’;
        },
        fuck:function(o){
            o.innerHTML += ‘o！’;
        }
    });

    Y.Node.addDOMMethods(['eat','drink','shit','pee','fuck']);

    //runtime
    Y.get(‘#aperson’).eat().drink().shit().pee().fuck();
});
</code></pre>

<p>“Y.get(’#aperson’).eat().drink().shit().pee().fuck()“这句即是这个person一溜烟的执行了吃喝拉撒干的动作，连隔都不带打的。</p>

<p>在来看看不用任何库作的方法链式调用：</p>

<pre><code>var $ = function(id){
    var _$ = function(id){
        this.el = document.getElementById(id);
    };
    _$.prototype.eat = function(){
        this.el.innerHTML+=’吃！’;
        return this;
    };
    _$.prototype.drink= function(){
        this.el.innerHTML+=’喝！’;
        return this;
    };
    _$.prototype.shit = function(){
        this.el.innerHTML+=’拉！’;
        return this;
    };
    _$.prototype.pee = function(){
        this.el.innerHTML+=’撒！’;
        return this;
    };
    _$.prototype.fuck = function(){
        this.el.innerHTML+=’o！’;
        return this;
    };
    return new _$(id);
};

//runtime
$(‘aperson’).eat().drink().shit().pee().fuck();
</code></pre>

<p>这里的$(’aperson’).eat().drink().shit().pee().fuck()也是一溜烟的吃喝拉撒睡，但在实现具体方法的时候，每个方法都要return this，而真正灵活的扩展则不希望这样作。在js库流行的今天，这种降低耦合增加扩展性的小技巧显的尤为重要。</p>

</section>
<section class="meta">

<!--span class="tags">
  tagged by 
  
</span-->

<span class="time">
  posted at <time datetime="2009-02-01">2009-02-01</time>
</span>
</section>

<section class="comment">
<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'jayliblog'; // required: replace example with your forum shortname
	var disqus_identifier = 'urn:uuid:92001fdd-008c-4523-8e79-d67cb8ecf3e4';

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
</section>


        </article>
      </div>
    </div> <!--! end of #container -->
  </body>
</html>
